package com.lwbldy.common.plugins.logging.aspect;

import com.lwbldy.common.plugins.logging.domain.SysLogging;
import com.lwbldy.common.plugins.logging.enums.LoggingType;
import com.lwbldy.common.plugins.logging.factory.LoggingFactory;
import com.lwbldy.common.shiro.ShiroUtils;
import com.lwbldy.common.tools.ServletUtil;
import com.lwbldy.common.tools.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 日 志 切 面 实 现
 * */
@Aspect
@Component
public class LoggingAspect {

    @Resource
    private LoggingFactory loggingFactory;

    //
    ThreadLocal<Long> currentTime = new ThreadLocal<>();

    /**
     * 配置切入点
     * */
    @Pointcut("@annotation(com.lwbldy.common.plugins.logging.annotation.Logging) || @within(com.lwbldy.common.plugins.logging.annotation.Logging)")
    public void dsPointCut() { }

    /**
     * 处 理 系 统 日 志
     * */
    @Around("dsPointCut()")
    private Object around(ProceedingJoinPoint joinPoint) throws Throwable
    {
        SysLogging logging = new SysLogging();
        Object result;
        try {
            //获取开始时间
            currentTime.set(System.currentTimeMillis());

            // 执 行 方 法
            result = joinPoint.proceed();
            com.lwbldy.common.plugins.logging.annotation.Logging loggingAnnotation = getLogging(joinPoint);
            // 日 志 编 号
//            logging.setId(SequenceUtil.makeStringId());
            // 模 块 标 题
            logging.setTitle(loggingAnnotation.value());
            // 模 块 标 题
            logging.setTitle(loggingAnnotation.title());
            // 模 块 描 述
            logging.setDescription(loggingAnnotation.describe());
            // 业 务 类 型
            logging.setBusinessType(loggingAnnotation.type());
            // 是 否 成 功
            logging.setSuccess(true);
            // 日 志 类 型
            logging.setLoggingType(LoggingType.OPERATE);
            // 设置浏览器类型
            logging.setBrowser(ServletUtil.getBrowser());
            // 设置 访问 地址
            logging.setOperateAddress(ServletUtil.getRemoteHost());
            // 设置
            logging.setRequestMethod(ServletUtil.getMethod());
            try{
                logging.setOperateName(ShiroUtils.getUserId()+"");
            }catch (Exception e){
                logging.setOperateName("");
            }
            logging.setOperateUrl(ServletUtil.getRequestURI());
            logging.setCreateTime(new Date());

            // 方法路径
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            String methodName = joinPoint.getTarget().getClass().getName()+"."+signature.getName()+"()";
            logging.setMethod(methodName);

            StringBuilder params = new StringBuilder("{");
            //参数值
            List<Object> argValues = new ArrayList<>(Arrays.asList(joinPoint.getArgs()));
            //参数名称
            for (Object argValue : argValues) {
                params.append(argValue).append(" ");
            }
            logging.setRequestParam(params.toString() + " }");

        }catch (Exception exception){
            logging.setSuccess(false);
            logging.setErrorMsg(exception.getMessage());
            throw exception;
        }finally {

            logging.setTime(System.currentTimeMillis() - currentTime.get());
            currentTime.remove();

            System.out.println(logging);

            loggingFactory.record(logging);

        }
        return result;
    }

    /**
     * 获 取 注 解
     * */
    public com.lwbldy.common.plugins.logging.annotation.Logging getLogging(ProceedingJoinPoint point) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Class<? extends Object> targetClass = point.getTarget().getClass();
        com.lwbldy.common.plugins.logging.annotation.Logging targetLogging = targetClass.getAnnotation(com.lwbldy.common.plugins.logging.annotation.Logging.class);
        if ( targetLogging != null) {
            return targetLogging;
        } else {
            Method method = signature.getMethod();
            com.lwbldy.common.plugins.logging.annotation.Logging logging = method.getAnnotation(com.lwbldy.common.plugins.logging.annotation.Logging.class);
            return logging;
        }
    }

    public String getUsername() {
        try {
            return ShiroUtils.getUserEntity().getUsername();
        }catch (Exception e){
            return "";
        }
    }

}
